package br.com.listatel.modelo.dao;

import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;

import br.com.listatel.modelo.entidades.Contato;
import br.com.listatel.modelo.entidades.Endereco;
import br.com.listatel.modelo.entidades.Pessoa;
import br.com.listatel.modelo.frameworkDao.EngineConnection;
import br.com.listatel.modelo.frameworkDao.QueryMapper;

public class PessoaDao {
	private EngineConnection engineConn;

	public PessoaDao() {
		engineConn = new EngineConnection();
	}

	/**
	 * Método responsável por inserir o objeto no banco de dados
	 * 
	 * @param endereco
	 */
	public void inserir(Pessoa pessoa) {
		String sql = "INSERT INTO pessoa (nome, sobre_nome) VALUES(?,?)";

		try {
			engineConn.beginTransaction();
			long id = engineConn.executePreparedUpdateAndReturnGeneratedKeys(
					sql, pessoa.getNome(), pessoa.getSobrenome());
			pessoa.setId(id);
			engineConn.endTransaction();
		} catch (SQLException e) {
			engineConn.rollbackTransaction();
			e.printStackTrace();
		}
	}
	
	/**
	 * Método responsável por atribuir uma nova pessoa que já contenha um
	 * endereco
	 * 
	 * @param pessoa
	 */
	public void inserirPessoaComEnderecoInexistente(Pessoa pessoa) {
		EnderecoDao endDao = new EnderecoDao();
		endDao.inserir(pessoa.getEndereco());
		inserirEnderecoExistenteEmPessoa(pessoa);
	}

	/**
	 * Método responsável por atribuir uma nova pessoa que já contenha um
	 * contato
	 * 
	 * @param pessoa
	 */
	public void inserirPessoaComContatoInexistente(Pessoa pessoa) {
		ContatoDao conDao = new ContatoDao();
		conDao.inserir(pessoa.getContato());
		inserirContatoExistenteEmPessoa(pessoa);
	}

	/**
	 * Método responsável por inserir uma pessoa sem a existencia de
	 * um contato e um endereço salvados no banco.
	 * 
	 * @param pessoa
	 */
	public void inserirPessoaContatoEnderecoInexistentes(Pessoa pessoa)
	{
		inserir(pessoa);
		
		inserirPessoaComContatoInexistente(pessoa);
		inserirPessoaComEnderecoInexistente(pessoa);
	}
	
	/**
	 * Este método atribui um endereco na tabela pessoa
	 * 
	 * @param pessoa
	 */
	public void inserirEnderecoExistenteEmPessoa(Pessoa pessoa) {
		String sql = "UPDATE pessoa SET id_end = ? WHERE id_pessoa = ?";

		try {
			engineConn.beginTransaction();
			engineConn.executePreparedUpdateIntoContextTransaction(sql, pessoa
					.getEndereco().getId(), pessoa.getId());
			engineConn.endTransaction();
		} catch (SQLException e) {
			engineConn.rollbackTransaction();
			e.printStackTrace();
		}
	}

	/**
	 * Este método atribui um contato na tabela pessoa
	 * 
	 * @param pessoa
	 */
	public void inserirContatoExistenteEmPessoa(Pessoa pessoa) {
		String sql = "UPDATE pessoa SET id_contato = ? WHERE id_pessoa = ?";

		try {
			engineConn.beginTransaction();
			engineConn.executePreparedUpdateIntoContextTransaction(sql, pessoa
					.getContato().getId(), pessoa.getId());
			engineConn.endTransaction();
		} catch (SQLException e) {
			engineConn.rollbackTransaction();
			e.printStackTrace();
		}
	}

	/**
	 * Método responsável por atribuir uma nova pessoa no banco, que já contenha
	 * o contato e o endereco existentes
	 * 
	 * @param pessoa
	 */
	public void inserirPessoaComEndContExistente(Pessoa pessoa) {
		inserir(pessoa);
		inserirContatoExistenteEmPessoa(pessoa);
		inserirEnderecoExistenteEmPessoa(pessoa);
	}
	
	/**
	 * Responsável por atualizar dados no banco de dados
	 * 
	 * @param endereco
	 */
	public void atualizar(Pessoa pessoa) {
		String sql = "UPDATE pessoa SET nome = ?, sobre_nome = ? "
				+ "WHERE id_contato = ?";

		try {
			engineConn.beginTransaction();
			engineConn.executePreparedUpdateIntoContextTransaction(sql,
					pessoa.getNome(), pessoa.getSobrenome(), pessoa.getId());
			engineConn.endTransaction();
		} catch (SQLException e) {
			engineConn.rollbackTransaction();
			e.printStackTrace();
		}
	}

	/**
	 * Responsável por excluir dados do banco de dados
	 * 
	 * @param endereco
	 */
	public void excluir(Pessoa pessoa) {
		String sql = "DELETE FROM pessoa WHERE id_pessoa = ?";
		try {
			engineConn.beginTransaction();
			engineConn.executePreparedUpdateIntoContextTransaction(sql,
					pessoa.getId());
			engineConn.endTransaction();
		} catch (SQLException e) {
			engineConn.rollbackTransaction();
			e.printStackTrace();
		}
	}

	public ArrayList<Pessoa> listaTodos() {
		final ArrayList<Pessoa> pessoas = new ArrayList<Pessoa>();
		String sql = "SELECT * FROM pessoa";

		try {
			engineConn.executePreparedQuery(sql, new QueryMapper<Pessoa>() {

				@Override
				public List<Pessoa> mapping(ResultSet rset) throws SQLException {
					while (rset.next()) {
						Pessoa pessoa = new Pessoa();
						pessoa.setId(rset.getLong("id_pessoa"));
						pessoa.setNome(rset.getString("nome"));
						pessoa.setSobrenome(rset.getString("sobre_nome"));
						long idEnd = rset.getLong("id_end");
						long idContato = rset.getLong("id_contato");

						Endereco endereco = new Endereco();
						EnderecoDao endDao = new EnderecoDao();
						endereco = endDao.listaById(idEnd);
						pessoa.setEndereco(endereco);

						Contato contato = new Contato();
						ContatoDao contDao = new ContatoDao();
						contato = contDao.listaById(idContato);
						pessoa.setContato(contato);

						pessoas.add(pessoa);
					}
					return pessoas;
				}
			});
		} catch (SQLException e) {
			e.printStackTrace();
		}
		return pessoas;
	}
}
